package com.lqian.p1_concurrent_origin_3;

public class TestVisableDemo {
    private long count = 0;

    private void add10K(){
        int idx = 0;
        while(idx++ < 10000){
            count += 1;
        }
    }

    public static long calc() throws InterruptedException {
        final TestVisableDemo test = new TestVisableDemo();
        //创建两个线程，执行add()操作
        Thread t1 = new Thread(() -> {
            test.add10K();
        });
        Thread t2 = new Thread(() -> {
            test.add10K();
        });
        //启动两个线程
        t1.start();
        t2.start();
        //等待两个线程执行结束
        t1.join();
        t2.join();
        return test.count;
    }

    public static void main(String[] args) throws InterruptedException {
        long result = TestVisableDemo.calc();
        System.out.println(result);

        /**
         *  --> 直觉告诉我，这个结果应该是20000。
         *      因为在单线程中调用了2次add10K()方法，count的值应该为20000才对
         *      但实际上calc() 的执行结果是个 10000 到 20000 之间的随机数。
         *
         *  --> 为什么呢？
         *   我们假设线程A和线程B同时开始执行，那么第一次都会将count = 0 读取到
         *   格子的cpu缓存里，执行完count + 1之后，各自cpu缓存里的值都是1。同时写入内存后，
         *   我们会发现内存中都是1，而不是我们期望的2。
         *   之后，由于各自的cpu缓存里都有了count的值，两个线程都是基于cpu缓存里的count值来计算
         *   所以，最终会导致count的值都是小于20000的，这就是缓存的可见性问题
         *
         *   循环 10000 次 count+=1 操作如果改为循环 1 亿次，你会发现效果更明显，最终
         *   count 的值接近 1 亿，而不是 2 亿。如果循环 10000 次，count 的值接近 20000，
         *   原因是两个线程不是同时启动的，有一个时差。
         */

    }
}
